package com.seven.ezpermissions.helper

import android.content.Context
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.seven.ezpermissions.OnDeniedCallback
import com.seven.ezpermissions.OnDestroyEvent

/**
 * Permissions Helper
 * @author seven.xie
 * @date 2020/7/10 14:23
 * email: se7en.xie@qq.com
 */
abstract class PermissionsHelper<T> constructor(internal var host: T?) {

    companion object {

        fun newInstance(host: AppCompatActivity): PermissionsHelper<out AppCompatActivity> {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                return LowApiPermissionsHelper(host)
            }
            return AppCompatActivityPermissionsHelper(host)
        }

        fun newInstance(host: Fragment): PermissionsHelper<out Fragment> {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                return LowApiPermissionsHelper(host)
            }
            return FragmentPermissionsHelper(host)
        }
    }

    fun request(
        rationale: String,
        positiveButton: String,
        negativeButton: String,
        requestCode: Int,
        permissions: Array<out String>,
        onDeniedCallback: OnDeniedCallback?
    ) {
        if (shouldShowRationale(permissions)) {
            showRationale(
                rationale,
                positiveButton,
                negativeButton,
                requestCode,
                permissions,
                onDeniedCallback
            )
        } else {
            directRequest(requestCode, permissions)
        }
    }

    protected open fun onClear() {
        host = null
    }

    private fun shouldShowRationale(permissions: Array<out String>): Boolean {
        return permissions.any { permission -> shouldShowRationale(permission) }
    }

    abstract fun directRequest(requestCode: Int, permissions: Array<out String>)

    abstract fun shouldShowRationale(permission: String): Boolean

    abstract fun showRationale(
        rationale: String,
        positiveButton: String,
        negativeButton: String,
        requestCode: Int,
        permissions: Array<out String>,
        onDeniedCallback: OnDeniedCallback?
    )

    abstract fun addLifecycleObserver(observer: LifecycleObserver)

    abstract fun onStateChanged(
        source: LifecycleOwner,
        event: Lifecycle.Event,
        observer: LifecycleObserver,
        callback: OnDestroyEvent
    )

    abstract val context: Context?
}